// ---------------------------------------------------------------------------------------------------------------------
// SHIFT_REGISTERS.h
// ---------------------------------------------------------------------------------------------------------------------
// Project:	Alpha Branch Predictor
// Authors:	Jabeer Ahmed, 
// 			Omar Mohsin, 
// 			Fadi Butti
// Course:	ECE - 586 (Winter 2013)
// Prof:	Mark Faust
// Portland State University
// ---------------------------------------------------------------------------------------------------------------------

#ifndef __SHIFT_REGISTERS_H__
#define __SHIFT_REGISTERS_H__

#include "types.h"
#include <stdlib.h>

struct shift_reg10
{
	uint bits:10;
	shift_reg10():bits(0){};
	shift_reg10& operator++(int){bits = bits<<1 | 0x1; return *this;}	// insert 1
	shift_reg10& operator--(int){bits<<=1; return *this;} 				// insert 0 
};

struct shift_reg12
{
	uint bits:12;
	shift_reg12():bits(0){};
	shift_reg12& operator++(int){bits = bits<<1 | 0x1; return *this;}	// insert 1
	shift_reg12& operator--(int){bits<<=1; return *this;} 				// insert 0 
};

struct shift_reg 						
{
	uint bits;                                      // bool array for storing bits
	uint size; 										// size of the register
	uint val; 										// decimal value of the register
    uint mask;
    
	shift_reg(int len){  							// contructor with length as input
		bits = 0;                                   // Make the bool array of size len
		size = len; 								// set size of register to len
		val  = 0;									// initialize value of reg to 0
        mask = 1;
        mask<<=size;
        mask--;
    }
    
    shift_reg(const shift_reg& reg){
        this->size = reg.size;
        this->val = reg.val;
        this->bits = reg.bits;
        this->mask = reg.mask;
    }
    
    shift_reg& operator= (const shift_reg& reg){
        if (this != &reg){
            this->size = reg.size;
            this->val = reg.val;
            this->bits = reg.bits;
            this->mask = reg.mask;
        }
        return *this;
    }
    
	void push(bool bit){ 							// pushes bits in and calcs the value of the register
        bits<<=1;
        bits|=bit;
        bits&=mask;
        val = bits;    
    }
    
    friend ostream& operator<<(ostream& lhs, const shift_reg& rhs) 	// prints out the bits
    {																// e.g. usage: cout << reg << endl;
        uint m = 1<<(rhs.size-1);
        
        for (int i=rhs.size; i>0;i--){
            if (i%4 == 0) 
                lhs << " ";
			lhs << (bool)(rhs.bits & m); 
            m>>=1;
		}
        return lhs;
    }
};

#endif 	// __SHIFT_REGISTERS_H__